<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>一些知识点整理 | YTBlog</title>
    <meta name="generator" content="VuePress 1.5.2">
    
    <meta name="description" content="前端技术分享">
    <link rel="preload" href="/ytblog/assets/css/0.styles.cb920d31.css" as="style"><link rel="preload" href="/ytblog/assets/js/app.5ba5dcf6.js" as="script"><link rel="preload" href="/ytblog/assets/js/2.f25dafc3.js" as="script"><link rel="preload" href="/ytblog/assets/js/5.64df639e.js" as="script"><link rel="prefetch" href="/ytblog/assets/js/10.5a02d3b2.js"><link rel="prefetch" href="/ytblog/assets/js/11.44a85492.js"><link rel="prefetch" href="/ytblog/assets/js/12.66c94e70.js"><link rel="prefetch" href="/ytblog/assets/js/13.fbec9428.js"><link rel="prefetch" href="/ytblog/assets/js/3.1ec314c7.js"><link rel="prefetch" href="/ytblog/assets/js/4.6f6a54bd.js"><link rel="prefetch" href="/ytblog/assets/js/6.60c7b6d3.js"><link rel="prefetch" href="/ytblog/assets/js/7.7c06f209.js"><link rel="prefetch" href="/ytblog/assets/js/8.f6875229.js"><link rel="prefetch" href="/ytblog/assets/js/9.6f0d250c.js">
    <link rel="stylesheet" href="/ytblog/assets/css/0.styles.cb920d31.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/ytblog/" class="home-link router-link-active"><!----> <span class="site-name">YTBlog</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/ytblog/" class="nav-link">
  主页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="练手小项目" class="dropdown-title"><span class="title">练手小项目</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/ytblog/HTML/" class="nav-link">
  HTML&amp;CSS
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/JavaScript/" class="nav-link">
  JavaScript
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/jquery/" class="nav-link">
  jquery
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/vue/" class="nav-link">
  vue
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端一些概念理解" class="dropdown-title"><span class="title">前端一些概念理解</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/ytblog/CSS/" aria-current="page" class="nav-link router-link-exact-active router-link-active">
  知识点整理
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/ES6/" class="nav-link">
  读书笔记
</a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/ytblog/" class="nav-link">
  主页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="练手小项目" class="dropdown-title"><span class="title">练手小项目</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/ytblog/HTML/" class="nav-link">
  HTML&amp;CSS
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/JavaScript/" class="nav-link">
  JavaScript
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/jquery/" class="nav-link">
  jquery
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/vue/" class="nav-link">
  vue
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端一些概念理解" class="dropdown-title"><span class="title">前端一些概念理解</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/ytblog/CSS/" aria-current="page" class="nav-link router-link-exact-active router-link-active">
  知识点整理
</a></li><li class="dropdown-item"><!----> <a href="/ytblog/ES6/" class="nav-link">
  读书笔记
</a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>一些知识点整理</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/ytblog/CSS/#笔试常用操作" class="sidebar-link">笔试常用操作</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/ytblog/CSS/#数组常用操作" class="sidebar-link">数组常用操作</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#字符串常用操作" class="sidebar-link">字符串常用操作</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#math常用方法" class="sidebar-link">math常用方法</a></li></ul></li><li><a href="/ytblog/CSS/#斐波那契三种写法" class="sidebar-link">斐波那契三种写法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/ytblog/CSS/#跨域" class="sidebar-link">跨域</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/ytblog/CSS/#jsonp：" class="sidebar-link">jsonp：</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#跨域资源共享：cors" class="sidebar-link">跨域资源共享：CORS</a></li></ul></li><li><a href="/ytblog/CSS/#数组扁平化：" class="sidebar-link">数组扁平化：</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/ytblog/CSS/#浅拷贝" class="sidebar-link">浅拷贝</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#深拷贝" class="sidebar-link">深拷贝</a></li></ul></li><li><a href="/ytblog/CSS/#左边固定宽度右边自适应的方法" class="sidebar-link">左边固定宽度右边自适应的方法</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/ytblog/CSS/#flex方法：左边固定宽度，右边flex：1" class="sidebar-link">flex方法：左边固定宽度，右边flex：1</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#float方法：block不设置宽度会默认和父元素一样宽（margin-border-box）" class="sidebar-link">float方法：block不设置宽度会默认和父元素一样宽（margin+border-box）</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#inline-block方法：通过外边距左移，内边距内容推出，设置position置顶左边盒子，要注意html里换行的事情" class="sidebar-link">inline-block方法：通过外边距左移，内边距内容推出，设置position置顶左边盒子，要注意html里换行的事情</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#绝对定位方法：用内边距把内容推出，然后设置左边的position和z-index置顶" class="sidebar-link">绝对定位方法：用内边距把内容推出，然后设置左边的position和z-index置顶</a></li></ul></li><li><a href="/ytblog/CSS/#用reduce方法实现map功能" class="sidebar-link">用reduce方法实现map功能</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/ytblog/CSS/#event-loop-事件轮询" class="sidebar-link">Event loop 事件轮询</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/ytblog/CSS/#web安全" class="sidebar-link">web安全</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/ytblog/CSS/#_1-xss跨站脚本攻击" class="sidebar-link">1. XSS跨站脚本攻击</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#防御方法：" class="sidebar-link">防御方法：</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#_2-csrf：跨站请求伪造" class="sidebar-link">2. CSRF：跨站请求伪造</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#_3-点击劫持" class="sidebar-link">3. 点击劫持</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#_4-url跳转漏洞" class="sidebar-link">4. URL跳转漏洞</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#_5-sql注入" class="sidebar-link">5. SQL注入</a></li><li class="sidebar-sub-header"><a href="/ytblog/CSS/#_6-os命令注入攻击" class="sidebar-link">6. OS命令注入攻击</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="一些知识点整理"><a href="#一些知识点整理" class="header-anchor">#</a> 一些知识点整理</h1> <h2 id="笔试常用操作"><a href="#笔试常用操作" class="header-anchor">#</a> 笔试常用操作</h2> <h3 id="数组常用操作"><a href="#数组常用操作" class="header-anchor">#</a> 数组常用操作</h3> <p>Array.push()返回新的数组长度。原数组改变。Array.pop()，删除并返回数组的最后一个元素。原数组改变。</p> <p>Array.unshift()，向数组的开头添加一个或多个元素，并返回新的数组长度。原数组改变。</p> <p>Array.shift()，删除数组的第一项，并返回第一个元素的值。若该数组为空，则返回undefined。原数组改变。</p> <p>Array.concat(arr1,arr2...)，合并两个或多个数组，生成一个新的数组。原数组不变。或[...a,...b]</p> <p>Array.join()，将数组的每一项用指定字符连接形成一个字符串。默认连接字符为 “,” 逗号。</p> <p>Array.sort((a,b)=&gt;return a-b)，对数组元素进行排序。按照字符串UniCode码排序，原数组改变。(正数从小到大)</p> <p>Array.slice(start,end)，从start开始，end之前结束，不到end；如果不给end值，从start开始到数组结束。start可以给负值</p> <p>Array.splice(index,howmany,arr1,arr2...) ，删除元素并添加元素，从index位置开始删除howmany个元素，并将arr1、arr2...数据从index位置依次插入。howmany为0时，则不删除元素。原数组改变。</p> <p>Array.forEach(function（item，idex，arr）)array.filter(function(currentValue,index,arr), thisValue)</p> <p>array.map(function(currentValue,index,arr), thisValue)方法返回一个新数组。不会改变原始数组。</p> <p>array.every(function(currentValue,index,arr), thisValue)对数组中的每一项进行判断，若都符合则返回true，否则返回false。</p> <p>array.some(function(currentValue,index,arr),thisValue)对数组中的每一项进行判断，若都不符合则返回false，否则返回true。</p> <p>array.reduce(function(total, currentValue, currentIndex, arr), initialValue) 返回到total，最终结果是一个值，total</p> <p><em>array</em>.indexOf(<em>item</em>,<em>start</em>)，<em>array</em>.lastIndexOf(<em>item</em>,<em>start</em>)没有则返回-1，start代表截取位置。</p> <p>array.findIndex(function(currentValue, index, arr), thisValue)返回第一个true</p> <h3 id="字符串常用操作"><a href="#字符串常用操作" class="header-anchor">#</a> 字符串常用操作</h3> <p><em>string</em>.indexOf(<em>searchvalue</em>,<em>start</em>)	string.includes(searchvalue, start)	string*.lastIndexOf(<em>searchvalue</em>,<em>start</em>)</p> <p>string.includes(searchvalue, start)  可以是多个单词	string*.match(<em>regexp</em>)</p> <p><em>string</em>.replace(<em>searchvalue,newvalue</em>)	string*.slice(<em>start</em>,<em>end</em>) end不含</p> <p><em>string</em>.split(<em>separator</em>,<em>limit</em>)	<em>string</em>.substr(<em>start</em>,<em>length</em>)	string.substring(from, to) to不含</p> <h3 id="math常用方法"><a href="#math常用方法" class="header-anchor">#</a> math常用方法</h3> <p>ceil（x）向上舍入	exp（x）e的x次方	floor（x）向下取整	log（x）以e为底</p> <p>ronud 四舍五入	max（x，y，z）	pow（x，y）x的y次幂	rondom（）0到1（不含）随机数</p> <p>sqrt（x）平方根</p> <h2 id="斐波那契三种写法"><a href="#斐波那契三种写法" class="header-anchor">#</a> 斐波那契三种写法</h2> <div class="language-js extra-class"><pre class="language-js"><code>		<span class="token comment">//循环法</span>
		<span class="token keyword">function</span> <span class="token function">f1</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
			<span class="token keyword">let</span> pre <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
			<span class="token keyword">let</span> next <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
			<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>i<span class="token operator">&lt;</span>n<span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
				<span class="token punctuation">[</span>pre<span class="token punctuation">,</span>next<span class="token punctuation">]</span><span class="token operator">=</span><span class="token punctuation">[</span>next<span class="token punctuation">,</span>pre<span class="token operator">+</span>next<span class="token punctuation">]</span>
			<span class="token punctuation">}</span><span class="token punctuation">;</span>
			<span class="token keyword">return</span> next
		<span class="token punctuation">}</span>
		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f1</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
		<span class="token comment">//递归法</span>
		<span class="token keyword">function</span> <span class="token function">f2</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
			<span class="token keyword">if</span><span class="token punctuation">(</span>n<span class="token operator">==</span><span class="token number">0</span><span class="token operator">||</span>n<span class="token operator">==</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">return</span> n<span class="token punctuation">;</span>
			<span class="token keyword">return</span> <span class="token function">f2</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token function">f2</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span>
		<span class="token punctuation">}</span>
		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f2</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
		<span class="token comment">//闭包存储</span>
		<span class="token keyword">let</span> <span class="token function-variable function">f3</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
			<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
			<span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
				<span class="token keyword">let</span> res <span class="token operator">=</span> arr<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">;</span>
				<span class="token keyword">if</span><span class="token punctuation">(</span>res <span class="token operator">===</span> <span class="token keyword">undefined</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
					console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;嘿嘿嘿&quot;</span><span class="token punctuation">)</span>
					res <span class="token operator">=</span> <span class="token function">f3</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token function">f3</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span>
					arr<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token operator">=</span>res
				<span class="token punctuation">}</span>
				<span class="token keyword">return</span> res
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f3</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f3</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">f3</span><span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></div><p>**闭包函数：**声明在一个函数中的函数，叫做闭包函数。</p> <p>**闭包：**内部函数总是可以访问其所在的外部函数中声明的参数和变量，即使在其外部函数被返回（寿命终结）了之后。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">outerFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> 
  <span class="token keyword">function</span> <span class="token function">innerFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
      i<span class="token operator">++</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> innerFn<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> inner <span class="token operator">=</span> <span class="token function">outerFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">//每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同，都会重新创建一个新的地址</span>
<span class="token function">inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> inner2 <span class="token operator">=</span> <span class="token function">outerFn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">inner2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">inner2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">inner2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token comment">//1 2 3 1 2 3</span>
</code></pre></div><div class="language- extra-class"><pre class="language-text"><code>var lis = document.getElementsByTagName(&quot;li&quot;);
for(var i=0;i&lt;lis.length;i++){
  (function(i){
      lis[i].onclick = function(){
           console.log(i);
      };
  })(i);       //事件处理函数中闭包的写法
}  
</code></pre></div><h2 id="跨域"><a href="#跨域" class="header-anchor">#</a> 跨域</h2> <p>同源限制：</p> <div class="language- extra-class"><pre class="language-text"><code>1.) Cookie、LocalStorage 和 IndexDB 无法读取
2.) DOM 和 Js对象无法获得
3.) AJAX 请求不能发送
</code></pre></div><p>协议、端口、域名不同</p> <h3 id="jsonp："><a href="#jsonp：" class="header-anchor">#</a> jsonp：</h3> <div class="language- extra-class"><pre class="language-text"><code> &lt;script&gt;
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参一个回调函数名给后端，方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&amp;callback=handleCallback';
    document.head.appendChild(script);

    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 &lt;/script&gt;
 服务器端返回一个函数调用：
 handleCallback({&quot;status&quot;: true, &quot;user&quot;: &quot;admin&quot;})
</code></pre></div><p>缺点：只能使用get</p> <h4 id="document-domain-iframe跨域"><a href="#document-domain-iframe跨域" class="header-anchor">#</a> <strong>document.domain + iframe跨域</strong></h4> <p>1.）父窗口：(http://www.domain.com/a.html)</p> <div class="language- extra-class"><pre class="language-text"><code>&lt;iframe id=&quot;iframe&quot; src=&quot;http://child.domain.com/b.html&quot;&gt;&lt;/iframe&gt;
&lt;script&gt;
    document.domain = 'domain.com';
    var user = 'admin';
&lt;/script&gt;
</code></pre></div><p>2.）子窗口：(http://child.domain.com/b.html)</p> <div class="language- extra-class"><pre class="language-text"><code>&lt;script&gt;
    document.domain = 'domain.com';
    // 获取父窗口中变量
    alert('get js data from parent ---&gt; ' + window.parent.user);
&lt;/script&gt;
</code></pre></div><p>此方案仅限主域相同，子域不同的跨域应用场景。</p> <h4 id="location-hash-iframe跨域："><a href="#location-hash-iframe跨域：" class="header-anchor">#</a> <strong>location.hash + iframe跨域</strong>：</h4> <p>实现原理： a欲与b跨域相互通信，通过中间页c来实现。 三个页面，不同域之间利用iframe的location.hash传值，相同域之间直接js访问来通信。</p> <p>具体实现：A域：a.html -&gt; B域：b.html -&gt; A域：c.html，a与b不同域只能通过hash值单向通信，b与c也不同域也只能单向通信，但c与a同域，所以c可通过parent.parent访问a页面所有对象。</p> <h4 id="window-name-iframe跨域"><a href="#window-name-iframe跨域" class="header-anchor">#</a> <strong>window.name + iframe跨域</strong></h4> <h3 id="跨域资源共享：cors"><a href="#跨域资源共享：cors" class="header-anchor">#</a> 跨域资源共享：CORS</h3> <div class="language- extra-class"><pre class="language-text"><code>'Access-Control-Allow-Origin': 'http://www.domain1.com'
</code></pre></div><h4 id="nginx代理跨域"><a href="#nginx代理跨域" class="header-anchor">#</a> <strong>nginx代理跨域</strong></h4> <h5 id="nginx反向代理接口跨域"><a href="#nginx反向代理接口跨域" class="header-anchor">#</a> nginx反向代理接口跨域</h5> <p>跨域原理： 同源策略是浏览器的安全策略，不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议，不会执行JS脚本，不需要同源策略，也就不存在跨越问题。</p> <p>实现思路：通过nginx配置一个代理服务器（域名与domain1相同，端口不同）做跳板机，反向代理访问domain2接口，并且可以顺便修改cookie中domain信息，方便当前域cookie写入，实现跨域登录。</p> <p>反向代理隐藏了真实的服务端，当我们请求 www.baidu.com 的时候，就像拨打10086一样，背后可能有成千上万台服务器为我们服务，但具体是哪一台，你不知道，也不需要知道，你只需要知道反向代理服务器是谁就好了，www.baidu.com 就是我们的反向代理服务器，反向代理服务器会帮我们把请求转发到真实的服务器那里去。Nginx就是性能非常好的反向代理服务器，用来做负载均衡。</p> <h2 id="数组扁平化："><a href="#数组扁平化：" class="header-anchor">#</a> 数组扁平化：</h2> <p>转化成字符串再转回来：</p> <p>arr.toString().split(&quot;,&quot;)</p> <p>arr.join(&quot;,&quot;).split(&quot;,&quot;)</p> <p>递归：</p> <div class="language- extra-class"><pre><code>		function bph(arr){
			return arr.reduce((pre,item)=&gt;{
				if(Array.isArray(item)){
					console.log(&quot;递归&quot;,item)
					return pre.concat(bph(item))
				}else{
					console.log(&quot;运行push&quot;,item)
					pre.push(item)
					return pre
				}
			},[])
		}
		function bph2(arr){
			let res = [...arr]
			while(res.some((item)=&gt;Array.isArray(item))){
				console.log(res)
				res = [].concat(...res)
				console.log(res)
			}
			return res
		}
</code></pre></div><h3 id="浅拷贝"><a href="#浅拷贝" class="header-anchor">#</a> 浅拷贝</h3> <p>let newobj = Object.assign({},obj)</p> <h3 id="深拷贝"><a href="#深拷贝" class="header-anchor">#</a> 深拷贝</h3> <p>原型链上的属性会被for in循环出来</p> <p>递归方法：</p> <div class="language- extra-class"><pre><code>		function deepCopy(obj){
			let newobj = Array.isArray(obj)?[]:{};
			for(let i in obj){
				if(obj.hasOwnProperty(i)){
					if(typeof obj[i] ==='object'){
						newobj[i] = deepCopy(obj[i])
					}else{
						newobj[i] = obj[i]
					}
				}
			}
			return newobj
		}
</code></pre></div><p>json方法</p> <p>JSON.parse(JSON.stringify(obj)) 缺点：无法拷贝函数</p> <p>1.每个对象都具有一个名为__proto__的属性；</p> <p>2.每个构造函数（构造函数标准为大写开头，如Function()，Object()等等JS中自带的构造函数，以及自己创建的）都具有一个名为prototype的方法（注意：既然是方法，那么就是一个对象（JS中函数同样是对象），所以prototype同样带有__proto__属性）；</p> <p>3.每个对象的__proto__属性指向自身构造函数的prototype；</p> <h2 id="左边固定宽度右边自适应的方法"><a href="#左边固定宽度右边自适应的方法" class="header-anchor">#</a> 左边固定宽度右边自适应的方法</h2> <h3 id="flex方法：左边固定宽度，右边flex：1"><a href="#flex方法：左边固定宽度，右边flex：1" class="header-anchor">#</a> flex方法：左边固定宽度，右边flex：1</h3> <h3 id="float方法：block不设置宽度会默认和父元素一样宽（margin-border-box）"><a href="#float方法：block不设置宽度会默认和父元素一样宽（margin-border-box）" class="header-anchor">#</a> float方法：block不设置宽度会默认和父元素一样宽（margin+border-box）</h3> <p>float+margin-left或者float+触发BFC</p> <div class="language-css extra-class"><pre class="language-css"><code> 			<span class="token selector">.left</span><span class="token punctuation">{</span>
				<span class="token property">float</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token selector">.right</span><span class="token punctuation">{</span>
				<span class="token property">margin-left</span><span class="token punctuation">:</span> 300px<span class="token punctuation">;</span>
			<span class="token punctuation">}</span> 
</code></pre></div><div class="language-css extra-class"><pre class="language-css"><code>			<span class="token selector">.left</span><span class="token punctuation">{</span>
				<span class="token property">float</span><span class="token punctuation">:</span> left<span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token selector">.right</span><span class="token punctuation">{</span>
				<span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
</code></pre></div><h3 id="inline-block方法：通过外边距左移，内边距内容推出，设置position置顶左边盒子，要注意html里换行的事情"><a href="#inline-block方法：通过外边距左移，内边距内容推出，设置position置顶左边盒子，要注意html里换行的事情" class="header-anchor">#</a> inline-block方法：通过外边距左移，内边距内容推出，设置position置顶左边盒子，要注意html里换行的事情</h3> <div class="language-css extra-class"><pre class="language-css"><code> 			<span class="token selector">.left</span><span class="token punctuation">{</span>
				<span class="token property">display</span><span class="token punctuation">:</span> inline-block<span class="token punctuation">;</span>
				<span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
			<span class="token selector">.right</span><span class="token punctuation">{</span>
				<span class="token property">display</span><span class="token punctuation">:</span> inline-block<span class="token punctuation">;</span>
				<span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
				<span class="token property">margin-left</span><span class="token punctuation">:</span> -300px<span class="token punctuation">;</span>
				<span class="token property">padding-left</span><span class="token punctuation">:</span> 300px<span class="token punctuation">;</span>
			<span class="token punctuation">}</span>
</code></pre></div><h3 id="绝对定位方法：用内边距把内容推出，然后设置左边的position和z-index置顶"><a href="#绝对定位方法：用内边距把内容推出，然后设置左边的position和z-index置顶" class="header-anchor">#</a> 绝对定位方法：用内边距把内容推出，然后设置左边的position和z-index置顶</h3> <div class="language- extra-class"><pre class="language-text"><code>			.left{
				position: relative;
				z-index: 1;
			}
			.right{
				position: absolute;
				width: 100%;
				padding-left: 300px;
				left: 0;
				top: 0;
			}
</code></pre></div><h2 id="用reduce方法实现map功能"><a href="#用reduce方法实现map功能" class="header-anchor">#</a> 用reduce方法实现map功能</h2> <p>reduce的输入参数有两个，一个函数，一个initvalue，用法如下</p> <div class="language-js extra-class"><pre class="language-js"><code>			<span class="token keyword">var</span> res1 <span class="token operator">=</span> arr1<span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">pre<span class="token punctuation">,</span>item<span class="token punctuation">,</span>index<span class="token punctuation">,</span>arr</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token keyword">return</span> pre<span class="token operator">+</span>item<span class="token punctuation">}</span><span class="token punctuation">)</span>
			console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res1<span class="token punctuation">)</span>
</code></pre></div><p>其中遍历过程的每个return都会保存到pre中，最后的返回值也就是pre。如果第二个参数initvalue不设置的话第一个参数会被跳过，即pre==第一个参数，item==第二个参数。</p> <p>map的输入参数同样有两个，一个函数，一个thisvalue，用法如下</p> <div class="language-js extra-class"><pre class="language-js"><code>			<span class="token keyword">var</span> res2 <span class="token operator">=</span> arr1<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">item<span class="token punctuation">,</span>index<span class="token punctuation">,</span>arr</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
				<span class="token keyword">return</span> item<span class="token operator">+</span><span class="token number">1</span>
			<span class="token punctuation">}</span><span class="token punctuation">,</span>arr2<span class="token punctuation">)</span>
</code></pre></div><p>thisvalue 的值会在回调函数的this产生替代。</p> <p>所以用reduce实现map的功能如下</p> <div class="language-js extra-class"><pre class="language-js"><code>			<span class="token class-name">Array</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">myMap</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">fn<span class="token punctuation">,</span>thisvalue</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
				<span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
				thisvalue <span class="token operator">=</span> thisvalue<span class="token operator">||</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
				<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">pre<span class="token punctuation">,</span>item<span class="token punctuation">,</span>index<span class="token punctuation">,</span>arr</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
					result<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span>item<span class="token punctuation">,</span>index<span class="token punctuation">,</span>arr<span class="token punctuation">)</span><span class="token punctuation">)</span>
					<span class="token keyword">return</span>
				<span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span>
				<span class="token keyword">return</span> result
			<span class="token punctuation">}</span>
</code></pre></div><p>initvalue我们可以设置为任意值，因为无所谓，我们不用reduce 的返回值，只用它的遍历功能</p> <p>如果要把thisvalue也加进去即fn.call(thisvalue,item,index,arr)</p> <h2 id="event-loop-事件轮询"><a href="#event-loop-事件轮询" class="header-anchor">#</a> Event loop 事件轮询</h2> <p>JavaScript的单线程，与它的用途有关。作为浏览器脚本语言，JavaScript的主要用途是与用户互动，以及操作DOM。这决定了它只能是单线程，否则会带来很复杂的同步问题。比如，假定JavaScript同时有两个线程，一个线程在某个DOM节点上添加内容，另一个线程删除了这个节点，这时浏览器应该以哪个线程为准？</p> <p><img src="https://img2018.cnblogs.com/blog/1725163/201907/1725163-20190702145817811-46244406.png" alt="img"></p> <p><strong>宏队列，macrotask，也叫tasks。</strong> 一些异步任务的回调会依次进入macro task queue，等待后续被调用，这些异步任务包括：</p> <ul><li>setTimeout</li> <li>setInterval</li> <li>setImmediate (Node独有)</li> <li>requestAnimationFrame (浏览器独有)</li> <li>I/O</li> <li>UI rendering (浏览器独有)</li></ul> <p><strong>微队列，microtask，也叫jobs。</strong> 另一些异步任务的回调会依次进入micro task queue，等待后续被调用，这些异步任务包括：</p> <ul><li>process.nextTick (Node独有)</li> <li>Promise</li> <li>Object.observe</li> <li>MutationObserve</li></ul> <ol><li>执行全局Script同步代码，这些同步代码有一些是同步语句，有一些是异步语句（比如setTimeout等）；</li> <li>全局Script代码执行完毕后，调用栈Stack会清空；</li> <li>从微队列microtask queue中取出位于队首的回调任务，放入调用栈Stack中执行，执行完后microtask queue长度减1；</li> <li>继续取出位于队首的任务，放入调用栈Stack中执行，以此类推，直到直到把microtask queue中的所有任务都执行完毕。<strong>注意，如果在执行microtask的过程中，又产生了microtask，那么会加入到队列的末尾，也会在这个周期被调用执行</strong>；</li> <li>microtask queue中的所有任务都执行完毕，此时microtask queue为空队列，调用栈Stack也为空；</li> <li>取出宏队列macrotask queue中位于队首的任务，放入Stack中执行；</li> <li>执行完毕后，调用栈Stack为空；</li> <li>重复第3-7个步骤；</li> <li>重复第3-7个步骤；</li></ol> <h2 id="web安全"><a href="#web安全" class="header-anchor">#</a> web安全</h2> <h3 id="_1-xss跨站脚本攻击"><a href="#_1-xss跨站脚本攻击" class="header-anchor">#</a> 1. XSS跨站脚本攻击</h3> <p>跨站脚本攻击是指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或JavaScript进行的一种攻击。</p> <p>跨站脚本攻击有可能造成以下影响:</p> <ul><li>利用虚假输入表单骗取用户个人信息。</li> <li>利用脚本窃取用户的Cookie值，被害者在不知情的情况下，帮助攻击者发送恶意请求。</li> <li>显示伪造的文章或图片。</li></ul> <p><strong>XSS 的原理是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码，当用户浏览该页之时，嵌入其中 Web 里面的脚本代码会被执行，从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的</strong>。</p> <h4 id="非持久型xss（反射型xss）："><a href="#非持久型xss（反射型xss）：" class="header-anchor">#</a> 非持久型XSS（反射型XSS）：</h4> <p>通过给别人发送<strong>带有恶意脚本代码参数的 URL</strong></p> <p>比如页面中带有url解析：location.href.substring(location.href.indexOf('default=') + 8)</p> <p>那么通过生成一个url自动运行代码：https://xxx.com/xxx?default=<script>alert(document.cookie)</script></p> <p>即可进行攻击。</p> <p>非持久型 XSS 漏洞攻击有以下几点特征：</p> <ul><li>即时性，不经过服务器存储，直接通过 HTTP 的 GET 和 POST 请求就能完成一次攻击，拿到用户隐私数据。</li> <li>攻击者需要诱骗点击,必须要通过用户点击链接才能发起</li> <li>反馈率低，所以较难发现和响应修复</li> <li>盗取用户敏感保密信息</li></ul> <p>为了防止出现非持久型 XSS 漏洞，需要确保这么几件事情：</p> <ul><li>Web 页面渲染的所有内容或者渲染的数据都必须来自于服务端。</li> <li>尽量不要从 <code>URL</code>，<code>document.referrer</code>，<code>document.forms</code> 等这种 DOM API 中获取数据直接渲染。</li> <li>尽量不要使用 <code>eval</code>, <code>new Function()</code>，<code>document.write()</code>，<code>document.writeln()</code>，<code>window.setInterval()</code>，<code>window.setTimeout()</code>，<code>innerHTML</code>，<code>document.createElement()</code> 等可执行字符串的方法。</li> <li>如果做不到以上几点，也必须对涉及 DOM 渲染的方法传入的字符串参数做 escape 转义。</li> <li>前端渲染的时候对任何的字段都需要做 escape 转义编码。</li></ul> <h4 id="持久型xss："><a href="#持久型xss：" class="header-anchor">#</a> 持久型XSS：</h4> <p>持久型 XSS 漏洞，一般存在于 Form 表单提交等交互功能，如文章留言，提交文本信息等，黑客利用的 XSS 漏洞，将内容经正常功能提交进入数据库持久保存，当前端页面获得后端从数据库中读出的注入代码时，恰好将其渲染执行。</p> <p>比如提交回复带有script标签，那么别的用户打开这个页面时可能会自动运行这个代码。</p> <h3 id="防御方法："><a href="#防御方法：" class="header-anchor">#</a> 防御方法：</h3> <p><strong>1) CSP</strong></p> <p>CSP 本质上就是建立白名单，开发者明确告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则，如何拦截是由浏览器自己实现的。我们可以通过这种方式来尽量减少 XSS 攻击。</p> <p>通常可以通过两种方式来开启 CSP：</p> <ul><li>设置 HTTP Header 中的 Content-Security-Policy</li> <li>设置 meta 标签的方式</li></ul> <p>这里以设置 HTTP Header 来举例：</p> <ul><li>只允许加载本站资源</li></ul> <div class="language- extra-class"><pre class="language-text"><code>Content-Security-Policy: default-src 'self'
</code></pre></div><ul><li>只允许加载 HTTPS 协议图片</li></ul> <div class="language- extra-class"><pre class="language-text"><code>Content-Security-Policy: img-src https://*
</code></pre></div><ul><li>允许加载任何来源框架</li></ul> <div class="language- extra-class"><pre class="language-text"><code>Content-Security-Policy: child-src 'none'
</code></pre></div><h5 id="_2）转义字符"><a href="#_2）转义字符" class="header-anchor">#</a> 2）转义字符 &lt;</h5> <p><strong>3) HttpOnly Cookie。</strong></p> <p>这是预防XSS攻击窃取用户cookie最有效的防御手段。Web应用程序在设置cookie时，将其属性设为HttpOnly，就可以避免该网页的cookie被客户端恶意JavaScript窃取，保护用户cookie信息。</p> <h3 id="_2-csrf：跨站请求伪造"><a href="#_2-csrf：跨站请求伪造" class="header-anchor">#</a> 2. CSRF：跨站请求伪造</h3> <p><img src="https://image.fundebug.com/2019-01-31-04.png" alt="img"></p> <p>完成 CSRF 攻击必须要有三个条件：</p> <ul><li>用户已经登录了站点 A，并在本地记录了 cookie</li> <li>在用户没有登出站点 A 的情况下（也就是 cookie 生效的情况下），访问了恶意攻击者提供的引诱危险站点 B (B 站点要求访问站点A)。</li> <li>站点 A 没有做任何 CSRF 防御</li></ul> <p>我们来看一个例子： 当我们登入转账页面后，突然眼前一亮<strong>惊现&quot;XXX隐私照片，不看后悔一辈子&quot;的链接</strong>，耐不住内心躁动，立马点击了该危险的网站（页面代码如下图所示），但当这页面一加载，便会执行<code>submitForm</code>这个方法来提交转账请求，从而将10块转给黑客。</p> <p><img src="https://image.fundebug.com/2019-01-31-05.png" alt="img"></p> <h4 id="_2-如何防御"><a href="#_2-如何防御" class="header-anchor">#</a> 2.如何防御</h4> <p>防范 CSRF 攻击可以遵循以下几种规则：</p> <ul><li>Get 请求不对数据进行修改</li> <li>不让第三方网站访问到用户 Cookie</li> <li>阻止第三方网站请求接口</li> <li>请求时附带验证信息，比如验证码或者 Token</li></ul> <p><strong>1) SameSite</strong></p> <p>可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送，可以很大程度减少 CSRF 的攻击，但是该属性目前并不是所有浏览器都兼容。</p> <p><strong>2) Referer Check</strong></p> <p>HTTP Referer是header的一部分，当浏览器向web服务器发送请求时，一般会带上Referer信息告诉服务器是从哪个页面链接过来的，服务器籍此可以获得一些信息用于处理。可以通过检查请求的来源来防御CSRF攻击。正常请求的referer具有一定规律，如在提交表单的referer必定是在该页面发起的请求。所以<strong>通过检查http包头referer的值是不是这个页面，来判断是不是CSRF攻击</strong>。</p> <p>但在某些情况下如从https跳转到http，浏览器处于安全考虑，不会发送referer，服务器就无法进行check了。若与该网站同域的其他网站有XSS漏洞，那么攻击者可以在其他网站注入恶意脚本，受害者进入了此类同域的网址，也会遭受攻击。出于以上原因，无法完全依赖Referer Check作为防御CSRF的主要手段。但是可以通过Referer Check来监控CSRF攻击的发生。</p> <p><strong>3) Anti CSRF Token</strong></p> <p>目前比较完善的解决方案是加入Anti-CSRF-Token。即发送请求时在HTTP 请求中以参数的形式加入一个随机产生的token，并在服务器建立一个拦截器来验证这个token。服务器读取浏览器当前域cookie中这个token值，会进行校验该请求当中的token和cookie当中的token值是否都存在且相等，才认为这是合法的请求。否则认为这次请求是违法的，拒绝该次服务。</p> <p><strong>这种方法相比Referer检查要安全很多</strong>，token可以在用户登陆后产生并放于session或cookie中，然后在每次请求时服务器把token从session或cookie中拿出，与本次请求中的token 进行比对。由于token的存在，攻击者无法再构造出一个完整的URL实施CSRF攻击。但在处理多个页面共存问题时，当某个页面消耗掉token后，其他页面的表单保存的还是被消耗掉的那个token，其他页面的表单提交时会出现token错误。</p> <p><strong>4) 验证码</strong></p> <p>应用程序和用户进行交互过程中，特别是账户交易这种核心步骤，强制用户输入验证码，才能完成最终请求。在通常情况下，验证码够很好地遏制CSRF攻击。<strong>但增加验证码降低了用户的体验，网站不能给所有的操作都加上验证码</strong>。所以只能将验证码作为一种辅助手段，在关键业务点设置验证码。</p> <h3 id="_3-点击劫持"><a href="#_3-点击劫持" class="header-anchor">#</a> 3. 点击劫持</h3> <p>攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中，并将 iframe 设置为透明，在页面中透出一个按钮诱导用户点击。</p> <p>用户在登陆 A 网站的系统后，被攻击者诱惑打开第三方网站，而第三方网站通过 iframe 引入了 A 网站的页面内容，用户在第三方网站中点击某个按钮（被装饰的按钮），实际上是点击了 A 网站的按钮。
接下来我们举个例子：我在优酷发布了很多视频，想让更多的人关注它，就可以通过点击劫持来实现</p> <p>从上图可知，攻击者通过图片作为页面背景，隐藏了用户操作的真实界面，当你按耐不住好奇点击按钮以后，真正的点击的其实是隐藏的那个页面的订阅按钮，然后就会在你不知情的情况下订阅了。</p> <p><strong>1）X-FRAME-OPTIONS</strong></p> <p><code>X-FRAME-OPTIONS</code>是一个 HTTP 响应头，在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防御用 iframe 嵌套的点击劫持攻击。</p> <p>该响应头有三个值可选，分别是</p> <ul><li>DENY，表示页面不允许通过 iframe 的方式展示</li> <li>SAMEORIGIN，表示页面可以在相同域名下通过 iframe 的方式展示</li> <li>ALLOW-FROM，表示页面可以在指定来源的 iframe 中展示</li></ul> <p><strong>2）JavaScript 防御</strong></p> <p>对于某些远古浏览器来说，并不能支持上面的这种方式，那我们只有通过 JS 的方式来防御点击劫持了。</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>click-jack<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token style"><span class="token language-css">
    <span class="token selector">html</span> <span class="token punctuation">{</span>
      <span class="token property">display</span><span class="token punctuation">:</span> none <span class="token important">!important</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
    <span class="token keyword">if</span> <span class="token punctuation">(</span>self <span class="token operator">==</span> top<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">var</span> style <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'click-jack'</span><span class="token punctuation">)</span>
      document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>style<span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      top<span class="token punctuation">.</span>location <span class="token operator">=</span> self<span class="token punctuation">.</span>location
    <span class="token punctuation">}</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>以上代码的作用就是当通过 iframe 的方式加载页面时，攻击者的网页直接不显示所有内容了。</p> <h3 id="_4-url跳转漏洞"><a href="#_4-url跳转漏洞" class="header-anchor">#</a> 4. URL跳转漏洞</h3> <h4 id="_1-url跳转漏洞原理"><a href="#_1-url跳转漏洞原理" class="header-anchor">#</a> 1.URL跳转漏洞原理</h4> <p>黑客利用URL跳转漏洞来诱导安全意识低的用户点击，导致用户信息泄露或者资金的流失。其原理是黑客构建恶意链接(链接需要进行伪装,尽可能迷惑),发在QQ群或者是浏览量多的贴吧/论坛中。
安全意识低的用户点击后,经过服务器或者浏览器解析后，跳到恶意的网站中。</p> <p>http://gate.baidu.com/index?act=go&amp;url=http://t.cn/RVTatrd</p> <h4 id="_2-实现方式："><a href="#_2-实现方式：" class="header-anchor">#</a> 2.实现方式：</h4> <ul><li>Header头跳转</li> <li>Javascript跳转</li> <li>META标签跳转</li></ul> <p>这里我们举个Header头跳转实现方式：</p> <div class="language-php extra-class"><pre class="language-php"><code><span class="token php language-php"><span class="token delimiter important">&lt;?php</span>
<span class="token variable">$url</span><span class="token operator">=</span><span class="token variable">$_GET</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'jumpto'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token function">header</span><span class="token punctuation">(</span><span class="token double-quoted-string string">&quot;Location: <span class="token interpolation"><span class="token variable">$url</span></span>&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token delimiter important">?&gt;</span></span>
http://www.wooyun.org/login.php?jumpto=http://www.evil.com
</code></pre></div><p>这里用户会认为<code>www.wooyun.org</code>都是可信的，但是点击上述链接将导致用户最终访问<code>www.evil.com</code>这个恶意网址。</p> <h4 id="_3-如何防御"><a href="#_3-如何防御" class="header-anchor">#</a> 3.如何防御</h4> <p><strong>1)referer的限制</strong></p> <p>如果确定传递URL参数进入的来源，我们可以通过该方式实现安全限制，保证该URL的有效性，避免恶意用户自己生成跳转链接</p> <p><strong>2)加入有效性验证Token</strong></p> <p>我们保证所有生成的链接都是来自于我们可信域的，通过在生成的链接里加入用户不可控的Token对生成的链接进行校验，可以避免用户生成自己的恶意链接从而被利用，但是如果功能本身要求比较开放，可能导致有一定的限制。</p> <h3 id="_5-sql注入"><a href="#_5-sql注入" class="header-anchor">#</a> 5. SQL注入</h3> <p>SQL注入是一种常见的Web安全漏洞，攻击者利用这个漏洞，可以访问或修改数据，或者利用潜在的数据库漏洞进行攻击。</p> <h4 id="_1-sql注入的原理"><a href="#_1-sql注入的原理" class="header-anchor">#</a> 1.SQL注入的原理</h4> <p>我们先举一个万能钥匙的例子来说明其原理：</p> <p><img src="https://image.fundebug.com/2019-01-31-10.png" alt="img"></p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>/login<span class="token punctuation">&quot;</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>POST<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>Username: <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>username<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>Password: <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>password<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>password<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>submit<span class="token punctuation">&quot;</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>登陆<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>后端的 SQL 语句可能是如下这样的：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">let</span> querySQL <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
    SELECT *
    FROM user
    WHERE username='</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>username<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'
    AND psw='</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>password<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'
</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
</code></pre></div><p>这是我们经常见到的登录页面，但如果有一个恶意攻击者输入的用户名是 <code>admin' --</code>，密码随意输入，就可以直接登入系统了。why! ----这就是SQL注入</p> <p>我们之前预想的SQL 语句是:</p> <div class="language-sql extra-class"><pre class="language-sql"><code><span class="token keyword">SELECT</span> <span class="token operator">*</span> <span class="token keyword">FROM</span> <span class="token keyword">user</span> <span class="token keyword">WHERE</span> username<span class="token operator">=</span><span class="token string">'admin'</span> <span class="token operator">AND</span> psw<span class="token operator">=</span><span class="token string">'password'</span>
</code></pre></div><p>但是恶意攻击者用奇怪用户名将你的 SQL 语句变成了如下形式：</p> <div class="language-sql extra-class"><pre class="language-sql"><code><span class="token keyword">SELECT</span> <span class="token operator">*</span> <span class="token keyword">FROM</span> <span class="token keyword">user</span> <span class="token keyword">WHERE</span> username<span class="token operator">=</span><span class="token string">'admin'</span> <span class="token comment">--' AND psw='xxxx'</span>
</code></pre></div><p>在 SQL 中,<code>' --</code>是闭合和注释的意思，-- 是注释后面的内容的意思，所以查询语句就变成了：</p> <div class="language-sql extra-class"><pre class="language-sql"><code><span class="token keyword">SELECT</span> <span class="token operator">*</span> <span class="token keyword">FROM</span> <span class="token keyword">user</span> <span class="token keyword">WHERE</span> username<span class="token operator">=</span><span class="token string">'admin'</span>
</code></pre></div><p>所谓的万能密码,本质上就是SQL注入的一种利用方式。</p> <p>一次SQL注入的过程包括以下几个过程：</p> <ul><li>获取用户请求参数</li> <li>拼接到代码当中</li> <li>SQL语句按照我们构造参数的语义执行成功</li></ul> <p>我们会发现SQL注入流程中与正常请求服务器类似，只是黑客控制了数据，构造了SQL查询，而正常的请求不会SQL查询这一步，<strong>SQL注入的本质:数据和代码未分离，即数据当做了代码来执行。</strong></p> <h4 id="_2-危害"><a href="#_2-危害" class="header-anchor">#</a> 2.危害</h4> <ul><li>获取数据库信息
<ul><li>管理员后台用户名和密码</li> <li>获取其他数据库敏感信息：用户名、密码、手机号码、身份证、银行卡信息……</li> <li>整个数据库：脱裤</li></ul></li> <li>获取服务器权限</li> <li>植入Webshell，获取服务器后门</li> <li>读取服务器敏感文件</li></ul> <h4 id="_3-如何防御-2"><a href="#_3-如何防御-2" class="header-anchor">#</a> 3.如何防御</h4> <ul><li><strong>严格限制Web应用的数据库的操作权限</strong>，给此用户提供仅仅能够满足其工作的最低权限，从而最大限度的减少注入攻击对数据库的危害</li> <li><strong>后端代码检查输入的数据是否符合预期</strong>，严格限制变量的类型，例如使用正则表达式进行一些匹配处理。</li> <li><strong>对进入数据库的特殊字符（'，&quot;，，&lt;，&gt;，&amp;，*，; 等）进行转义处理，或编码转换</strong>。基本上所有的后端语言都有对字符串进行转义处理的方法，比如 lodash 的 lodash._escapehtmlchar 库。</li> <li><strong>所有的查询语句建议使用数据库提供的参数化查询接口</strong>，参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中，即不要直接拼接 SQL 语句。例如 Node.js 中的 mysqljs 库的 query 方法中的 ? 占位参数。</li></ul> <h3 id="_6-os命令注入攻击"><a href="#_6-os命令注入攻击" class="header-anchor">#</a> 6. OS命令注入攻击</h3> <p>OS命令注入和SQL注入差不多，只不过SQL注入是针对数据库的，而OS命令注入是针对操作系统的。OS命令注入攻击指通过Web应用，执行非法的操作系统命令达到攻击的目的。只要在能调用Shell函数的地方就有存在被攻击的风险。倘若调用Shell时存在疏漏，就可以执行插入的非法命令。</p> <p>命令注入攻击可以向Shell发送命令，让Windows或Linux操作系统的命令行启动程序。也就是说，通过命令注入攻击可执行操作系统上安装着的各种程序。</p> <h4 id="_1-原理"><a href="#_1-原理" class="header-anchor">#</a> 1.原理</h4> <p><img src="https://image.fundebug.com/2019-01-31-12.png" alt="img"></p> <p>黑客构造命令提交给web应用程序，web应用程序提取黑客构造的命令，拼接到被执行的命令中，因黑客注入的命令打破了原有命令结构，导致web应用执行了额外的命令，最后web应用程序将执行的结果输出到响应页面中。</p> <p>我们通过一个例子来说明其原理，假如需要实现一个需求：用户提交一些内容到服务器，然后在服务器执行一些系统命令去返回一个结果给用户</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token comment">// 以 Node.js 为例，假如在接口中需要从 github 下载用户指定的 repo</span>
<span class="token keyword">const</span> exec <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mz/child_process'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>exec<span class="token punctuation">;</span>
<span class="token keyword">let</span> params <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token comment">/* 用户输入的参数 */</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">exec</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">git clone </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>params<span class="token punctuation">.</span>repo<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> /some/path</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>如果 <code>params.repo</code> 传入的是 <code>https://github.com/admin/admin.github.io.git</code> 确实能从指定的 git repo 上下载到想要的代码。
但是如果 <code>params.repo</code> 传入的是 <code>https://github.com/xx/xx.git &amp;&amp; rm -rf /* &amp;&amp;</code> 恰好你的服务是用 root 权限起的就糟糕了。</p> <h4 id="_2-如何防御-2"><a href="#_2-如何防御-2" class="header-anchor">#</a> 2.如何防御</h4> <ul><li>后端对前端提交内容进行规则限制（比如正则表达式）。</li> <li>在调用系统命令前对所有传入参数进行命令行参数转义过滤。</li> <li>不要直接拼接命令语句，借助一些工具做拼接、转义预处理，例如 Node.js 的 <code>shell-escape npm</code>包</li></ul></div> <footer class="page-edit"><!----> <!----></footer> <!----> </main></div><div class="global-ui"></div></div>
    <script src="/ytblog/assets/js/app.5ba5dcf6.js" defer></script><script src="/ytblog/assets/js/2.f25dafc3.js" defer></script><script src="/ytblog/assets/js/5.64df639e.js" defer></script>
  </body>
</html>
